const DRAW = 0;//平局
const COMP_LOSS = -1;
const COMP_WIN = 1;

// 计算机下棋算法
function MoveInfo(position, value) {
  this.position = position;
  this.value = value;
}

function Computer(data) {
  this.data = [];
 
  for (let i = 0; i < 3; i++) {
    for (let j = 0; j < 3; j++) {
      this.data[3 * i + j] = data[i][j];
    }
  }

  this.findCompMove = function() {
    let i, responseValue, value, bestMove = -1;
    let quickWinInfo;
    if (this.fullBoard()) {
      value = DRAW;
    } else if ((quickWinInfo = this.immediateWin(1))) {
      return quickWinInfo;
    } else {
      value = COMP_LOSS;
      for (let i = 0; i < 9; i++) {
        if (this.data[i] === -1) {
          this.place(i, 1);
          responseValue = this.findHumanMove().value;
          this.unPlace(i);

          if (responseValue > value) {
            //update best move
            value = responseValue;
            bestMove = i;
          }
        }
      }

    }
    return new MoveInfo(bestMove, value);
  }

  this.findHumanMove = function() {
    let i, responseValue, value, bestMove = -1;
    let quickWinInfo;
    if (this.fullBoard()) {
      value = DRAW;;
    } else if ((quickWinInfo = this.immediateWin(0))) {
      return quickWinInfo;
    } else {
      value = COMP_WIN;
      for (let i = 0; i < 9; i++) {
        if (this.data[i] === -1) {
          this.place(i, 0);
          responseValue = this.findCompMove().value;
          this.unPlace(i);

          if (responseValue < value) {
            //update best move
            value = responseValue;
            bestMove = i;
          }
        }
      }

    }
    return new MoveInfo(bestMove, value);
  }

  this.fullBoard = function () {
    for (let i = 0; i < this.data.length; i++) {
      if (this.data[i] === -1) {
        return false;
      }
    }
    return true;
  }

  this.immediateWin = function (role) {
    for (let i = 0; i < 9; i++) {
      if (this.data[i] !== -1) {
        continue;
      }
      this.place(i, role);
      if (this.isWin(role)) {
        this.unPlace(i);
        return new MoveInfo(i, role === 0 ? -1 : 1);
      } else {
        this.unPlace(i);
      }
    }
  }

  this.isWin = function (role) {
    let isRowComplete, isColumnComplete, isDiagonalComplete;
    for (let i = 0; i < 3; i++) {
      isRowComplete = true;
      isColumnComplete = true;

      if (i < 2) {
        isDiagonalComplete = true;
      }

      for (let j = 0; j < 3; j++) {
        //横
        if (isRowComplete && this.data[3 * i + j] !== role) {
          isRowComplete = false;
        }
        //竖
        if (isColumnComplete && this.data[i + 3 * j] !== role) {//竖
          isColumnComplete = false;
        }
        if (i < 2 && isDiagonalComplete && this.data[4 * j + 6 * i*(1 - j)] != role) {//斜 0,4,8;4,6,2
          //[j + 2 * i * (1 - j)][j]->3j+6i*(1-j)+j->4*j+6*i(1-j)
          isDiagonalComplete = false;
        }

      }
      if (isRowComplete || isColumnComplete || isDiagonalComplete) {
        return true;
      }
    }
    return false;

  }

  this.place = function(i, role) {
    this.data[i] = role;
  }

  this.unPlace = function(i) {
    this.data[i] = -1;
  }



}

module.exports = {
  Computer: Computer
}